<?php

/**
 * Description of CURLManager
 *
 * @author Gvozd
 */
require_once(dirname(__FILE__) . '/EventDispatcher.php');
require_once(dirname(__FILE__) . '/multiCURL.php');

class CURLManager extends EventDispatcher {

    protected static $instance;
    public $mhs = array();
    public static $size_download = 0;
    public static $size_upload = 0;
    private $is_init = false;

    private function __construct() {
        $this->init();
    }

    public function init() {
        if ($this->is_init == false) {
            Tick::getInstance()->addEventListener('tick', array($this, 'tickListener'));
            $this->is_init = true;
        }
    }

    private function __clone() {
        
    }

    public static function getInstance() {
        return (null === self::$instance) ?
                self::$instance = new self() :
                self::$instance;
    }

    function tickListener(Event $event) {
        //usleep(10000);
        foreach ($this->mhs as $mh_key => $mh_entity) {
            $mrc = curl_multi_exec($mh_entity['mh'], $active);
            for ($i = $active, $count = count($mh_entity['chs']); $i < $count; $i++) {
                $info = curl_multi_info_read($mh_entity['mh']);
                foreach ($mh_entity['chs'] as $key => $ch_entity) {
                    if ($ch_entity->ch === $info['handle']) {
                        $ch_entity->result = curl_multi_getcontent($ch_entity->ch);
                        $ch_entity->info = curl_getinfo($ch_entity->ch);
                        /*
                        fseek($ch_entity->headerfile, 0);
                        $tmp_headers = fread($ch_entity->headerfile, 100000);
                        fclose($ch_entity->headerfile);
                        $tmp_headers = explode("\r\n\r\n", $tmp_headers);
                        $last_headers = '';
                        foreach ($tmp_headers as $key => $value) {
                            if(strlen($value)) {
                                $last_headers = $value;
                            }
                        }
                        $ch_entity->info['tmp_headers'] = $tmp_headers;
                        $ch_entity->info['response_header'] = explode("\r\n", $last_headers);
                        */
                        if (curl_errno($ch_entity->ch) != 0) {
                            $errno = curl_errno($ch_entity->ch);
                            $ch_entity->error[$errno] = curl_error($ch_entity->ch);
                        }

                        $this::$size_download += $ch_entity->info['size_download'];
                        $this::$size_upload += $ch_entity->info['size_upload'];


                        curl_multi_remove_handle($mh_entity['mh'], $ch_entity->ch);
                        curl_close($ch_entity->ch);
                        unset($this->mhs[$mh_key]['chs'][$key]);
                        $ch_entity->endFilter->addBoth(function($arg) use($ch_entity) {
                            $ch_entity->dispatchEvent(new Event('onLoad'));
                            $ch_entity->dispatchEvent(new Event('taskEnded'));
                            return $arg;
                        });
                        $ch_entity->endFilter->callback($ch_entity);
                        //var_dump($ch_entity);
                        break;
                    }
                }
            }
        }
        $total_counter = 0;
        foreach ($this->mhs as $mh_entity) {
            $total_counter += count($mh_entity['chs']);
        }
        if (0 == $total_counter) {
            $event->target->removeEventListener($event->type, $event->callee);
            $this->is_init = false;
        }
    }

    function addTask(multiCURL $task) {
        $use_key = null;
        foreach ($this->mhs as $key => $arr) {
            if (count($arr['chs']) < 10) {
                $use_key = $key;
                break;
            }
        }
        if (null === $use_key) {
            end($this->mhs);
            $use_key = key($this->mhs) + 1;
            $this->mhs[$use_key] = array('mh' => curl_multi_init(), 'chs' => array());
        }
        curl_multi_add_handle($this->mhs[$use_key]['mh'], $task->ch);
        $this->mhs[$use_key]['chs'][] = $task;
    }

}